// i.r(t), i.d(t, { default: () => CursorMesh })
import Module from "./Module"
import SymbolList from "../SymbolList"
import * as THREE from "three"
import CursorData from "../data/CursorData"
import RaycasterData from "../data/RaycasterData"
import RenderLayers, { RenderLayer } from "../utils/RenderLayers"
import d from "../shader/69383"
import u from "../shader/31090"
import p from "../shader/92903"
import m from "../shader/77179"
import funcUtil from "../utils/func.util"
const f = {
  extensions: { derivatives: !0 },
  defines: { RING_COUNT: 0, USE_TEXTURE: !1 },
  uniforms: {
    discRadius: { value: 0.2 },
    discNormal: { value: new THREE.Vector3(0, 0, 1) },
    ringRadii: { value: [] },
    ringColors: { value: [] },
    opacity: { value: 1 },
    texture: { value: null }
  },
  vertexShader: funcUtil.addNR(d, p),
  fragmentShader: funcUtil.addNR(u, m),
  side: THREE.FrontSide,
  transparent: !0
}
import AdaptiveRawShaderMaterial from "../material/AdaptiveRawShaderMaterial"
import renderOrderEnum from "../enum/renderOrder.enum"
import styleEnum from "../enum/style.enum"
import WebGLScene from "../three/WebGLScene"
import Engine from "../Engine"
import EngineContext from "../EngineContext"
import WebGLRendererModule from "./WebGLRendererModule"

const y = new THREE.Color(),
  b = [
    {
      outerRadius: 0.977,
      innerRadius: 0.926,
      color: 16777215,
      opacity: 1
    },
    {
      outerRadius: 0.898,
      innerRadius: 0.648,
      color: 16777215,
      opacity: 0.73
    }
  ]
class ReticleMaterial extends AdaptiveRawShaderMaterial {
  constructor(e = b) {
    super(f),
      this.setRings(e),
      Object.defineProperty(this, "opacity", {
        set(e) {
          this.uniforms.opacity.value = e
        },
        get() {
          return this.uniforms.opacity.value
        }
      })
  }
  setDiscNormal(e) {
    this.uniforms.discNormal.value.copy(e)
  }
  setDiscRadius(e) {
    this.uniforms.discRadius.value = e
  }
  setRings(e) {
    e = e || []
    this.defines.RING_COUNT !== e.length && ((this.defines.RING_COUNT = e.length), (this.needsUpdate = !0))
    this.uniforms.ringRadii.value = e.map(({ innerRadius: e, outerRadius: t }) => new THREE.Vector2(e, t))
    this.uniforms.ringColors.value = e.map(({ color: e, opacity: t }) => (y.set(e), new THREE.Vector4(y.r, y.g, y.b, t)))
  }
  setTexture(e) {
    this.defines.USE_TEXTURE !== !!e && ((this.defines.USE_TEXTURE = !!e), (this.needsUpdate = !0))
    this.uniforms.texture.value = e
  }
  getTexture() {
    return this.uniforms.texture.value
  }
}
class Cursor {
  scene: WebGLScene
  layer: RenderLayer
  supportsMobile: boolean
  style: number
  bindings: any[]
  onOpacityUpdate: (e: any) => void
  material: any
  onPositionUpdate: (e: any) => void
  container: any
  constructor(e: WebGLScene, t = RenderLayers.ALL) {
    this.scene = e
    this.layer = t
    this.supportsMobile = !1
    this.style = styleEnum.Reticle
    this.bindings = []
    this.onOpacityUpdate = e => {
      this.material.opacity = e.opacity.value
    }
    this.onPositionUpdate = e => {
      if (e.hit && e.hit.face) {
        const t = e.hit.point.clone()
        const i = e.hit.face.normal
        this.container.position.copy(t), this.material.setDiscNormal(i)
      }
    }
    this.container = new THREE.Group()
    this.container.name = "cursor"
    const i = new THREE.SphereGeometry(0.25, 8, 6)
    this.material = new ReticleMaterial()
    this.material.setDiscRadius(0.2)
    const n = new THREE.Mesh(i, this.material)
    this.container.add(n)
    n.renderOrder = renderOrderEnum.reticule
    n.layers.mask = this.layer.mask
  }
  init() {}
  render() {}
  dispose() {
    this.material.getTexture()?.dispose()
    this.container.children.forEach(e => {
      if (e.isMesh) {
        e.geometry.dispose()
        const t = e.material
        t.dispose(), t.map && t.map.dispose()
      }
    })
  }
  async activate(e: Engine) {
    const t = await e.market.waitForData(CursorData)
    const i = await e.market.waitForData(RaycasterData)
    this.bindings.push(t.onChanged(this.onOpacityUpdate), i.onChanged(this.onPositionUpdate))
    this.scene.add(this.container)
  }
  deactivate() {
    for (const e of this.bindings) e.cancel()
    this.bindings.length = 0
    this.scene.remove(this.container)
  }
  setVisible(e) {
    this.container.visible = e
  }
}
export default class CursorMesh extends Module {
  setVisible: (e: any) => void
  cursor: any
  constructor() {
    super(...arguments), (this.name = "cursor-mesh")
    this.setVisible = e => {
      this.cursor && this.cursor.setVisible(e)
    }
  }
  async init(e, t: EngineContext) {
    const i = (await t.getModuleBySymbol<WebGLRendererModule>(SymbolList.WEBGL_RENDERER)).getScene()
    const n = t.claimRenderLayer(this.name)
    this.cursor = new Cursor(i, n)
    t.addComponent(this, this.cursor)
  }
  get container() {
    return this.cursor.container
  }
}
